package com.core.shared;

import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.util.CellRangeAddress;

import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * User: xianfei
 * Date: 15-12-11
 * Time: 下午2:40
 * To change this template use File | Settings | File Templates.
 */
public class ExportExcel {

    // 导出表的标题
    private String title;
    // 导出表的列名
    private String[] rowName;

    private String title2;
    private String[] rowName2;

    private List<Object[]> dataList = new ArrayList<>();

    private List<Object[]> dataList2 = new ArrayList<>();

    /*HSSF － 提供读写Microsoft Excel XLS格式档案的功能。
    XSSF － 提供读写Microsoft Excel OOXML XLSX格式档案的功能。
    HWPF － 提供读写Microsoft Word DOC97格式档案的功能。
    XWPF － 提供读写Microsoft Word DOC2003格式档案的功能。
    HSLF － 提供读写Microsoft PowerPoint格式档案的功能。
    HDGF － 提供读Microsoft Visio格式档案的功能。
    HPBF － 提供读Microsoft Publisher格式档案的功能。
    HSMF － 提供读Microsoft Outlook格式档案的功能。*/

    // 构造方法，标题，列名数组，数据集
    public ExportExcel(String title, String[] rowName, List<Object[]> datalist) {
        this.dataList = datalist;
        this.rowName = rowName;
        this.title = title;
    }

    /**
     * 导出Excel数据 每个sheet的最大数据条数是：50000
     *
     * @param response 导出Excel的响应信息
     * @param filename 文件名
     * @throws Exception 异常
     */
    public void export(HttpServletResponse response, String filename) throws Exception {
        // 导出Excel的响应信息
        String headStr = "attachment; filename=\"" + new String(filename.getBytes("UTF-8"), "iso8859-1") + "\"";
        response.setContentType("APPLICATION/OCTET-STREAM");
        response.setHeader("Content-Disposition", headStr);
        // 输出流
        OutputStream out = response.getOutputStream();
        // 创建工作簿对象
        SXSSFWorkbook workbook = new SXSSFWorkbook(100);
        // sheet样式定义  getColumnTopStyle(),getStyle()均为自定义方法
        // 获取列头样式对象
        CellStyle columnTopStyle = this.getColumnTopStyle(workbook);
        // 单元格样式对象
        CellStyle style = this.getStyle(workbook);
        // 总的数据条数
        int rowsCount = dataList.size();
        // 每个sheet的最大数据条数
        int sheetMaxRowCount = 50000;
        int sheetIndex = rowsCount / sheetMaxRowCount;
        // 遍历每个sheet，并赋值
        for (int a = 0; a <= sheetIndex; a++) {
            // 创建工作表
            SXSSFSheet sheet = workbook.createSheet(title + a);
            // 产生表格标题行
            SXSSFRow rowm = sheet.createRow(0);
            SXSSFCell cellTiltle = rowm.createCell(0);
            // 合并单元格
            sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, (rowName.length - 1)));
            // 设置标题样式
            cellTiltle.setCellStyle(columnTopStyle);
            // 设置标题值
            cellTiltle.setCellValue(title);

            // 定义所需列数
            int columnNum = rowName.length;
            // 在索引2的位置创建行(最顶端的行开始的第二行)
            SXSSFRow rowRowName = sheet.createRow(2);
            // 将列头设置到sheet的单元格中
            for (int n = 0; n < columnNum; n++) {
                // 创建列头对应个数的单元格
                SXSSFCell cellRowName = rowRowName.createCell(n);
                // 设置列头单元格的数据类型
                cellRowName.setCellType(XSSFCell.CELL_TYPE_STRING);
                // 获取列头单元格值
                XSSFRichTextString text = new XSSFRichTextString(rowName[n]);
                // 设置列头单元格的值
                cellRowName.setCellValue(text);
                // 设置列头单元格样式
                cellRowName.setCellStyle(columnTopStyle);
                // 设置列宽
                sheet.setColumnWidth(n, (text.toString().getBytes().length + 8) * 256);
            }
            // 每个sheet的初始行号
            int sheetRowNum = a * sheetMaxRowCount;
            // 最后一个sheet的数据条数
            int lastRowCount = rowsCount % sheetMaxRowCount;
            if (a == sheetIndex) {
                sheetMaxRowCount = lastRowCount;
            }
            // 将查询出的数据设置到sheet对应的单元格中
            for (int i = 0; i < sheetMaxRowCount; i++) {
                // 创建所需的行数
                SXSSFRow row = sheet.createRow(i + 3);
                // 遍历每个对象
                Object[] obj = dataList.get(sheetRowNum + i);
                for (int j = 0; j < obj.length; j++) {
                    SXSSFCell cell; // 定义列的单元格
                    if (j == 0) {// 第一列
                        cell = row.createCell(j, SXSSFCell.CELL_TYPE_NUMERIC);
                        cell.setCellValue(sheetRowNum + i + 1);
                    } else {// 剩余列
                        cell = row.createCell(j, SXSSFCell.CELL_TYPE_STRING);
                        if (!"".equals(obj[j]) && obj[j] != null) {
                            // 设置单元格的值
                            cell.setCellValue(obj[j].toString());
                        } else {
                            cell.setCellValue("");
                        }
                    }
                    // 设置单元格样式
                    cell.setCellStyle(style);
                }
            }
        }
        workbook.write(out);
        out.close();
    }

    public void export2(HttpServletResponse response, String filename) throws Exception {
        // 导出Excel的响应信息
        String headStr = "attachment; filename=\"" + new String(filename.getBytes("UTF-8"), "iso8859-1") + "\"";
        response.setContentType("APPLICATION/OCTET-STREAM");
        response.setHeader("Content-Disposition", headStr);
        // 输出流
        OutputStream out = response.getOutputStream();
        // 创建工作簿对象
        SXSSFWorkbook workbook = new SXSSFWorkbook(100);
        // sheet样式定义【getColumnTopStyle()/getStyle()均为自定义方法 - 在下面 - 可扩展】
        CellStyle columnTopStyle = this.getColumnTopStyle(workbook);// 获取列头样式对象
        CellStyle style = this.getStyle(workbook); // 单元格样式对象
        int rowsCount = dataList.size();// 总的数据条数
        int sheetMaxRowCount = 50000;// 每个sheet的最大数据条数
        int sheetIndex = rowsCount / sheetMaxRowCount;
        // 遍历每个sheet，并赋值
        for (int a = 0; a <= sheetIndex; a++) {
            SXSSFSheet sheet = workbook.createSheet(title); // 创建工作表
            // 产生表格标题行
            SXSSFRow rowm = sheet.createRow(0);
            SXSSFCell cellTiltle = rowm.createCell(0);
            sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, (rowName.length - 1))); // 合并单元格
            cellTiltle.setCellStyle(columnTopStyle);// 设置标题样式
            cellTiltle.setCellValue(title);// 设置标题值

            int columnNum = rowName.length;// 定义所需列数
            SXSSFRow rowRowName = sheet.createRow(2); // 在索引2的位置创建行(最顶端的行开始的第二行)
            // 将列头设置到sheet的单元格中
            for (int n = 0; n < columnNum; n++) {
                SXSSFCell cellRowName = rowRowName.createCell(n); // 创建列头对应个数的单元格
                cellRowName.setCellType(SXSSFCell.CELL_TYPE_STRING); // 设置列头单元格的数据类型
                XSSFRichTextString text = new XSSFRichTextString(rowName[n]);// 获取列头单元格值
                cellRowName.setCellValue(text); // 设置列头单元格的值
                cellRowName.setCellStyle(columnTopStyle); // 设置列头单元格样式
                sheet.setColumnWidth(n, (text.toString().getBytes().length + 8) * 256);// 设置列宽
            }
            // 每个sheet的初始行号
            int sheetRowNum = a * sheetMaxRowCount;
            // 最后一个sheet的数据条数
            int lastRowCount = rowsCount % sheetMaxRowCount;
            if (a == sheetIndex) {
                sheetMaxRowCount = lastRowCount;
            }
            // 将查询出的数据设置到sheet对应的单元格中
            for (int i = 0; i < sheetMaxRowCount; i++) {
                SXSSFRow row = sheet.createRow(i + 3);// 创建所需的行数
                Object[] obj = dataList.get(sheetRowNum + i);// 遍历每个对象
                for (int j = 0; j < obj.length; j++) {
                    SXSSFCell cell = row.createCell(j); // 定义列的单元格
                    if (j == 0) {// 第一列
                        cell = row.createCell(j, SXSSFCell.CELL_TYPE_NUMERIC);
                        cell.setCellValue(sheetRowNum + i + 1);
                    } else {// 剩余列
                        cell = row.createCell(j, SXSSFCell.CELL_TYPE_STRING);
                        if (!"".equals(obj[j]) && obj[j] != null) {
                            cell.setCellValue(obj[j].toString());// 设置单元格的值
                        } else {
                            cell.setCellValue("");
                        }
                    }
                    cell.setCellStyle(style); // 设置单元格样式
                }
            }
        }

        int rowsCount2 = dataList2.size();// 总的数据条数
        int sheetMaxRowCount2 = 50000;// 每个sheet的最大数据条数
        int sheetIndex2 = rowsCount2 / sheetMaxRowCount2;
        // 遍历每个sheet，并赋值
        for (int a = 0; a <= sheetIndex2; a++) {
            SXSSFSheet sheet = workbook.createSheet(title2); // 创建工作表
            // 产生表格标题行
            SXSSFRow rowm = sheet.createRow(0);
            SXSSFCell cellTiltle = rowm.createCell(0);
            sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, (rowName2.length - 1))); // 合并单元格
            cellTiltle.setCellStyle(columnTopStyle);// 设置标题样式
            cellTiltle.setCellValue(title2);// 设置标题值

            int columnNum = rowName2.length;// 定义所需列数
            SXSSFRow rowRowName = sheet.createRow(2); // 在索引2的位置创建行(最顶端的行开始的第二行)
            // 将列头设置到sheet的单元格中
            for (int n = 0; n < columnNum; n++) {
                SXSSFCell cellRowName = rowRowName.createCell(n); // 创建列头对应个数的单元格
                cellRowName.setCellType(XSSFCell.CELL_TYPE_STRING); // 设置列头单元格的数据类型
                XSSFRichTextString text = new XSSFRichTextString(rowName2[n]);// 获取列头单元格值
                cellRowName.setCellValue(text); // 设置列头单元格的值
                cellRowName.setCellStyle(columnTopStyle); // 设置列头单元格样式
                sheet.setColumnWidth(n, (text.toString().getBytes().length + 8) * 256);// 设置列宽
            }
            // 每个sheet的初始行号
            int sheetRowNum = a * sheetMaxRowCount2;
            // 最后一个sheet的数据条数
            int lastRowCount = rowsCount2 % sheetMaxRowCount2;
            if (a == sheetIndex2) {
                sheetMaxRowCount2 = lastRowCount;
            }
            // 将查询出的数据设置到sheet对应的单元格中
            for (int i = 0; i < sheetMaxRowCount2; i++) {
                SXSSFRow row = sheet.createRow(i + 3);// 创建所需的行数
                Object[] obj = dataList2.get(sheetRowNum + i);// 遍历每个对象
                for (int j = 0; j < obj.length; j++) {
                    SXSSFCell cell = row.createCell(j); // 定义列的单元格
                    if (j == 0) {// 第一列
                        cell = row.createCell(j, SXSSFCell.CELL_TYPE_NUMERIC);
                        cell.setCellValue(sheetRowNum + i + 1);
                    } else {// 剩余列
                        cell = row.createCell(j, SXSSFCell.CELL_TYPE_STRING);
                        if (!"".equals(obj[j]) && obj[j] != null) {
                            cell.setCellValue(obj[j].toString());// 设置单元格的值
                        } else {
                            cell.setCellValue("");
                        }
                    }
                    cell.setCellStyle(style); // 设置单元格样式
                }
            }
        }

        workbook.write(out);
        out.close();
    }

    /*
     * 列头单元格样式
     */
    public CellStyle getColumnTopStyle(SXSSFWorkbook workbook) {
        // 设置字体
        Font font = workbook.createFont();
        // 设置字体大小
        font.setFontHeightInPoints((short) 11);
        // 字体加粗
        font.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);
        // 设置字体名字
        font.setFontName("Courier New");
        // 设置样式;
        CellStyle style = workbook.createCellStyle();
        // 设置底边框;
        style.setBorderBottom(XSSFCellStyle.BORDER_THIN);
        // 设置底边框颜色;
        style.setBottomBorderColor(HSSFColor.BLACK.index);
        // 设置左边框;
        style.setBorderLeft(XSSFCellStyle.BORDER_THIN);
        // 设置左边框颜色;
        style.setLeftBorderColor(HSSFColor.BLACK.index);
        // 设置右边框;
        style.setBorderRight(XSSFCellStyle.BORDER_THIN);
        // 设置右边框颜色;
        style.setRightBorderColor(HSSFColor.BLACK.index);
        // 设置顶边框;
        style.setBorderTop(XSSFCellStyle.BORDER_THIN);
        // 设置顶边框颜色;
        style.setTopBorderColor(HSSFColor.BLACK.index);
        // 在样式用应用设置的字体;
        style.setFont(font);
        // 设置自动换行;
        style.setWrapText(false);
        // 设置水平对齐的样式为居中对齐;
        style.setAlignment(XSSFCellStyle.ALIGN_CENTER);
        // 设置垂直对齐的样式为居中对齐;
        style.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
        return style;
    }

    /*
     * 列数据信息单元格样式
     */
    public CellStyle getStyle(SXSSFWorkbook workbook) {
        // 设置字体
        Font font = workbook.createFont();
        // 设置字体大小
        // font.setFontHeightInPoints((short)10);
        // 字体加粗
        // font.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);
        // 设置字体名字
        font.setFontName("Courier New");
        // 设置样式;
        CellStyle style = workbook.createCellStyle();
        // 设置底边框;
        style.setBorderBottom(XSSFCellStyle.BORDER_THIN);
        // 设置底边框颜色;
        style.setBottomBorderColor(HSSFColor.BLACK.index);
        // 设置左边框;
        style.setBorderLeft(XSSFCellStyle.BORDER_THIN);
        // 设置左边框颜色;
        style.setLeftBorderColor(HSSFColor.BLACK.index);
        // 设置右边框;
        style.setBorderRight(XSSFCellStyle.BORDER_THIN);
        // 设置右边框颜色;
        style.setRightBorderColor(HSSFColor.BLACK.index);
        // 设置顶边框;
        style.setBorderTop(XSSFCellStyle.BORDER_THIN);
        // 设置顶边框颜色;
        style.setTopBorderColor(HSSFColor.BLACK.index);
        // 在样式用应用设置的字体;
        style.setFont(font);
        // 设置自动换行;
        style.setWrapText(false);
        // 设置水平对齐的样式为居中对齐;
        style.setAlignment(XSSFCellStyle.ALIGN_CENTER);
        // 设置垂直对齐的样式为居中对齐;
        style.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
        return style;
    }

}
